﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;

namespace ICodeShare.UI.Controls
{
    /// <summary>
    /// 水印显示方式
    /// </summary>
    public enum WatermarkMode
    {
        /// <summary>
        /// 当文本框为空时就显示水印，不管该文本框有没有获得焦点
        /// </summary>
        TextEmtpy,
        /// <summary>
        /// 当文本框失去焦点且文本框没有内容时显示水印
        /// </summary>
        LostFocusedAndTextEmtpy,
    }

    /// <summary>
    /// TextBox文本框通用水印
    /// </summary>
    /// <remarks>add by zhidf 2017.9.3</remarks>
    public class WatermarkAdorner : Adorner
    {
        #region Members

        private TextBox adornedTextBox;
        private VisualCollection _visuals;
        private TextBlock textBlock;
        private WatermarkMode showMode;

        #endregion

        #region Constructors

        public WatermarkAdorner(UIElement adornedElement)
            : base(adornedElement)
        {
            if (adornedElement is TextBox)
            {
              
                adornedTextBox = adornedElement as TextBox;
                adornedTextBox.TextChanged += (s1, e1) =>
                {
                    this.SetWatermarkVisible(true);
                };
                adornedTextBox.GotFocus += (s1, e1) =>
                {
                    this.SetWatermarkVisible(true);
                };
                adornedTextBox.LostFocus += (s1, e1) =>
                {
                    this.SetWatermarkVisible(false);
                };

                _visuals = new VisualCollection(this);

                textBlock = new TextBlock()
                {
                    HorizontalAlignment =adornedTextBox.HorizontalContentAlignment,
                    VerticalAlignment = adornedTextBox.VerticalContentAlignment,
                    Text = WatermarkAdorner.GetWatermark(adornedElement),
                    Foreground = WatermarkAdorner.GetForeground(adornedElement),
                };
                if (adornedTextBox.HorizontalContentAlignment == HorizontalAlignment.Left || adornedTextBox.HorizontalContentAlignment == HorizontalAlignment.Stretch)
                {
                        textBlock.Margin = new Thickness(
                        adornedTextBox.Padding.Left + adornedTextBox.BorderThickness.Left + 2,
                        adornedTextBox.Padding.Top + adornedTextBox.BorderThickness.Top,
                        adornedTextBox.Padding.Right + adornedTextBox.BorderThickness.Right,
                        adornedTextBox.Padding.Bottom + adornedTextBox.BorderThickness.Bottom);
                }
                else
                {
                    textBlock.Margin = new Thickness(
                        adornedTextBox.Padding.Left + adornedTextBox.BorderThickness.Left,
                        adornedTextBox.Padding.Top + adornedTextBox.BorderThickness.Top,
                        adornedTextBox.Padding.Right + adornedTextBox.BorderThickness.Right,
                        adornedTextBox.Padding.Bottom + adornedTextBox.BorderThickness.Bottom);
                }

                _visuals.Add(textBlock);

                this.showMode = WatermarkAdorner.GetWatermarkShowMode(adornedElement);
            }
            this.IsHitTestVisible = false;
        }

        #endregion

        #region Dependency Property

        #region Watermark

        public static string GetWatermark(DependencyObject obj)
        {
            return (string)obj.GetValue(WatermarkProperty);
        }

        public static void SetWatermark(DependencyObject obj, string value)
        {
            obj.SetValue(WatermarkProperty, value);
        }

        public static readonly DependencyProperty WatermarkProperty = DependencyProperty.RegisterAttached(
            "Watermark",
            typeof(string),
            typeof(WatermarkAdorner),
            new PropertyMetadata(string.Empty, WatermarkChangedCallBack));

        private static void WatermarkChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var element = d as FrameworkElement;
            if (element != null)
            {
                var adornerLayer = AdornerLayer.GetAdornerLayer(element);

                if (adornerLayer != null)
                {
                    adornerLayer.Add(new WatermarkAdorner(element as UIElement));
                }
                else
                {
                    //layer为null，说明还未load过（整个可视化树中没有装饰层的情况不考虑）
                    //在控件的loaded事件内生成装饰件
                    element.Loaded += (s1, e1) =>
                    {
                        var adorner = new WatermarkAdorner(element);
                        var ad = AdornerLayer.GetAdornerLayer(element);
                        if (ad != null)
                        {
                            ad.Add(adorner);
                        }
                        //AdornerLayer.GetAdornerLayer(element).Add(adorner);
                    };
                }
            }
        }
        #endregion

        #region Foreground 字体颜色

        /// <summary>
        /// Gets the brush used to draw the mouse over font color.
        /// </summary>
        public static Brush GetForeground(DependencyObject element)
        {
            return (Brush)element.GetValue(ForegroundProperty);
        }

        /// <summary>
        /// Sets the brush used to draw the mouse over font color.
        /// </summary>
        public static void SetForeground(DependencyObject element, Brush value)
        {
            element.SetValue(ForegroundProperty, value);
        }

        /// <summary>
        /// DependencyProperty for <see cref="Foreground" /> property.
        /// </summary>
        public static readonly DependencyProperty ForegroundProperty = DependencyProperty.RegisterAttached(
            "Foreground",
            typeof(Brush),
            typeof(WatermarkAdorner),
            new FrameworkPropertyMetadata(new SolidColorBrush(Color.FromRgb(153, 153, 153))));
        #endregion Foreground 字体颜色

        #region FocusedOpacity 水印透明度

        public static double GetFocusedOpacity(DependencyObject obj)
        {
            return (double)obj.GetValue(FocusedOpacityProperty);
        }

        public static void SetFocusedOpacity(DependencyObject obj, double value)
        {
            obj.SetValue(FocusedOpacityProperty, value);
        }

        public static readonly DependencyProperty FocusedOpacityProperty = DependencyProperty.RegisterAttached(
            "FocusedOpacity",
            typeof(double),
            typeof(WatermarkAdorner),
            new PropertyMetadata(0.56));
        #endregion

        #region WatermarkShowMode

        public static WatermarkMode GetWatermarkShowMode(DependencyObject obj)
        {
            return (WatermarkMode)obj.GetValue(WatermarkShowModeProperty);
        }

        public static void SetWatermarkShowMode(DependencyObject obj, WatermarkMode value)
        {
            obj.SetValue(WatermarkShowModeProperty, value);
        }

        public static readonly DependencyProperty WatermarkShowModeProperty = DependencyProperty.RegisterAttached(
            "WatermarkShowMode",
            typeof(WatermarkMode),
            typeof(WatermarkAdorner),
            new PropertyMetadata(WatermarkMode.TextEmtpy));

        #endregion

        #endregion

        protected override int VisualChildrenCount
        {
            get
            {
                return _visuals.Count;
            }
        }

        protected override Visual GetVisualChild(int index)
        {
            return _visuals[index];
        }

        protected override Size MeasureOverride(Size constraint)
        {
            return base.MeasureOverride(constraint);
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            textBlock.Arrange(new Rect(finalSize));

            return base.ArrangeOverride(finalSize);
        }

        private void SetWatermarkVisible(bool isFocus)
        {
            this.textBlock.Opacity = 1.0;
            switch (this.showMode)
            {
                case WatermarkMode.TextEmtpy:
                    if (string.IsNullOrEmpty(this.adornedTextBox.Text))
                    {
                        this.textBlock.Visibility = Visibility.Visible;
                        if (isFocus)
                        {
                            this.textBlock.Opacity = GetFocusedOpacity(this);
                        }
                    }
                    else
                    {
                        this.textBlock.Visibility = Visibility.Collapsed;
                    }
                    break;
                case WatermarkMode.LostFocusedAndTextEmtpy:
                    if (!isFocus && string.IsNullOrEmpty(this.adornedTextBox.Text))
                    {
                        this.textBlock.Visibility = Visibility.Visible;
                    }
                    else
                    {
                        this.textBlock.Visibility = Visibility.Collapsed;
                    }
                    break;
                default:
                    break;
            }
        }
    }
}
